package com.qfmy.web.service.impl;

import com.github.pagehelper.PageHelper;
import com.qfmy.web.entity.MysqlDao.MysqlConfigDao;
import com.qfmy.web.entity.MysqlDao.TableInfo;
import com.qfmy.web.entity.minio.MinioProperties;
import com.qfmy.web.entity.minio.UploadFiled;
import com.qfmy.web.entity.page.PageBean;
import com.qfmy.web.mapper.OperateMapper;
import com.qfmy.web.service.OperateService;
import com.qfmy.web.utils.LoginUserHolder;
import io.jsonwebtoken.Claims;
import io.minio.*;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.FileInputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 *
 */
@Service
@SuppressWarnings("all")
public class OperateServiceImpl implements OperateService {
    //调用mapper接口进行查询
    @Resource
    private OperateMapper operateMapper;
    //定义一个查询所有的表的变量
    private String selectAll = "show tables";
    @Resource
    private MinioClient mc;
    @Resource
    private MinioProperties mp;

    /**
     * 获取所有的表
     * @return
     */
    @SneakyThrows
    @Override
    public List<TableInfo> getAllTable() {
        //获取当前用户的信息
        Claims claims = LoginUserHolder.get();
        //获取用户id
        Integer id = (Integer) claims.get("id");
        //查询所有的表
        return operateMapper.selectAll(id);
    }

    /**
     * 根据分页查询获取所有的表
     * @param pageNum 当前页
     * @param pageSize 每页条数
     * @param tableName 表名
     * @param createTime 创建时间
     * @return
     */
    @Override
    public PageBean<TableInfo> list(Integer pageNum, Integer pageSize, String tableName, String createTime) {
        //获取当前用户的信息
        Claims claims = LoginUserHolder.get();
        //获取用户id
        Integer id = (Integer) claims.get("id");
        //创建一个PageBean对象，并返回
        PageBean pageBean = new PageBean<>();
        //开启分页查询
        PageHelper.startPage(pageNum,pageSize);
        //查询所有表信息
        List<TableInfo> tableInfos = operateMapper.selectTableInfos(tableName,createTime,id);
        //设置总条数
        pageBean.setTotal(Long.valueOf(tableInfos.size()));
        //设置数据集合
        pageBean.setItems(tableInfos);
        return pageBean;
    }

    /**
     * 创建表
     * @param table
     */
    @Override
    public void addtable(@NotNull TableInfo table) {
        //获取当前用户的信息
        Claims claims = LoginUserHolder.get();
        //获取用户id
        Integer id = (Integer) claims.get("id");
        //设置用户id
        table.setUserId(id);
        //调用mapper接口进行插入操作
        operateMapper.insertTable(table);
    }

    /**
     * 根据表名删除表
     * @param tableName
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByTableName(String tableName) {
        //调用mapper接口进行删除操作
        operateMapper.deleteTable(tableName);
        //对应删除数据库的表
        //获取数据库的连接
        Connection connection = MysqlConfigDao.getConnection();
        //创建一个脚本执行器
        ScriptRunner scriptRunner = new ScriptRunner(connection);
        //设置脚本执行器的编码
        Resources.setCharset(Charset.forName("UTF-8"));
        scriptRunner.setSendFullScript(true);
        //执行脚本
        scriptRunner.runScript(new StringReader("drop table if exists " + tableName));
    }

    /**
     * 存放生成的代码文件
     * @param file
     * @return
     */
    @SneakyThrows
    @Override
    public void uploadFile(String path) {
        String url = null;
        //判断桶是否存在，不存在则创建
        boolean b = mc.bucketExists(BucketExistsArgs.builder()
                .bucket("auto-code-genarter").build());
        if (!b) {
            //创建桶
            mc.makeBucket(MakeBucketArgs.builder()
                    .bucket("auto-code-genarter").build());
            //设置桶策略
            mc.setBucketPolicy(SetBucketPolicyArgs.builder()
                    .bucket("auto-code-genarter")
                    .config(BuckerName("auto-code-genarter"))
                    .build());
        }
        //使用栈来实现递归->文件夹
        Stack<UploadFiled> stack=new Stack<>();
        File file= null;
        file= new File(path);
        UploadFiled uploadFiled = new UploadFiled();
        uploadFiled.file= file;
        uploadFiled.path= "";
        stack.push(uploadFiled);
        while(!stack.isEmpty())
        {
            UploadFiled tmp=stack.pop();
            file=tmp.file;
            String ParentPath=tmp.path;
            if(file.exists()) {
                String name = file.getName();
                if (file.isDirectory())
                {
                    List<File> fileList= Arrays.asList(file.listFiles());
                    for(File f:fileList)
                    {
                        UploadFiled uploadFileds = new UploadFiled();
                        uploadFileds.file= f;
                        uploadFileds.path= ParentPath+"/"+name;
                        stack.push(uploadFileds);
                    }
                }
                else
                {
                    try {
                        FileInputStream fileInputStream = new FileInputStream(file);
                        String minioPath= ParentPath+"/"+file.getName();
                        String substring = minioPath.substring(1, minioPath.length());
                        PutObjectArgs putObjectArgs=PutObjectArgs.builder().object(substring).stream(fileInputStream,fileInputStream.available(),-1).contentType("text/html").bucket(BuckerName("auto-code-genarter")).build();
                        mc.putObject(putObjectArgs);
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                }
            }
        }
    }


    /**
     * 获取桶的名称
     * @param bucketName
     * @return
     */
    public String BuckerName(String bucketName)
    {
        return """
                  {
                    "Statement" : [ {
                      "Action" : "s3:GetObject",
                      "Effect" : "Allow",
                      "Principal" : "*",
                      "Resource" : "arn:aws:s3:::%s/*"
                    } ],
                    "Version" : "2012-10-17"
                  }
                  """.formatted(bucketName);
    }

}
